package com.qianli.cashmama.product.server.facade;

import com.alibaba.fastjson.JSONObject;
import com.fqgj.common.api.Response;
import com.fqgj.common.api.enums.BasicErrorCodeEnum;
import com.fqgj.common.utils.CollectionUtils;
import com.fqgj.common.utils.StringUtils;
import com.fqgj.log.factory.LogFactory;
import com.fqgj.log.interfaces.Log;
import com.google.common.base.Strings;
import com.google.common.collect.ArrayListMultimap;
import com.google.common.collect.Maps;
import com.qianli.cashmama.product.facade.ProductFacade;
import com.qianli.cashmama.product.facade.enums.AuthTypeEnum;
import com.qianli.cashmama.product.facade.enums.ProductShelfTypeEnum;
import com.qianli.cashmama.product.facade.result.*;
import com.qianli.cashmama.product.server.domain.ProductCategoryDomain;
import com.qianli.cashmama.product.server.domain.ProductDomain;
import com.qianli.cashmama.product.server.domain.UserAuthTypeDomain;
import com.qianli.cashmama.product.server.exception.ProductException;
import com.qianli.cashmama.product.server.service.ProductService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Service("productFacade")
public class ProductFacadeImpl implements ProductFacade {

    private static final Log LOGGER = LogFactory.getLog(ProductFacadeImpl.class);

    @Autowired
    private ProductService productService;

    @Override
    public Response<List<ProductCategory>> getProductCategoryList(String appCode) {
        try {
            List<ProductCategoryDomain> list = productService.getProductCategoryList(appCode);
            List<ProductCategory> facadeList = new ArrayList<>();
            for (ProductCategoryDomain categoryDomain : list) {
                facadeList.add(categoryDomain.newFacade(false));
            }
            return Response.ok(facadeList);
        } catch (ProductException e) {
            return Response.error(e.getErrorCode());
        }
    }

    /**
     * 根据categoryCode获取认证信息
     */
    @Override
    public Response<CategoryAuthRef> getUserAuthByCategoryCode(String categoryCode) {
        return Response.error("Query failed");
    }

    /**
     * 获取所有的认证信息
     */
    @Override
    public Response<Map<String, UserAuth>> getAllUserAuth() {
        List<UserAuthTypeDomain> allUserAuth = productService.getAllUserAuth();
        ArrayListMultimap<String, UserAuthTypeDomain> domainMaps = ArrayListMultimap.create();
        Map<String, UserAuth> authMap = Maps.newConcurrentMap();
        for (UserAuthTypeDomain domain : allUserAuth) {
            domainMaps.put(domain.getTypeCode(), domain);
        }
        for (String typeCode : domainMaps.keySet()) {
            List<UserAuthTypeDomain> tmpList = domainMaps.get(typeCode);
            if (CollectionUtils.isNotEmpty(tmpList)) {
                // 设置name, subName
                UserAuth userAuth = new UserAuth();
                userAuth.setName(productService.getDictName(typeCode));
                /*long num = tmpList.stream().filter(userAuthTypeDomain ->
                        userAuthTypeDomain.getFlag().equals(String.valueOf(NecessaryEnum.OPTIONAL.getStatus()))).count();*/
                userAuth.setSubName(getTripText(typeCode));
                // 设置userAuthActon
                List<UserAuthAction> configData = tmpList.stream()
                        .map(categoryUserAuthDomain
                                -> JSONObject.parseObject(Strings.nullToEmpty(categoryUserAuthDomain.getConfigData()), UserAuthAction.class))
                        .collect(Collectors.toList());
                userAuth.setActoins(configData);

                authMap.put(typeCode, userAuth);

            }
        }
        return Response.ok(authMap);
    }

    private String getTripText(String typeCode) {
        String tripText = null;
        if (typeCode.equals(AuthTypeEnum.basicCertification.getCode())) {
            tripText = productService.getDictName("requiredTipText");
        } else if (typeCode.equals(AuthTypeEnum.optionalCertification.getCode())) {
            tripText = productService.getDictName("optionTipText");
        } else if (typeCode.equals(AuthTypeEnum.identityCertification.getCode())) {
            tripText = productService.getDictName("identityTipText");
        } else {
            tripText = "";
        }
        return tripText;
    }

    @Override
    public Response<List<Product>> getProductList(String productCategoryCode, boolean selectRules) {
        return getProductList(productCategoryCode, selectRules, true, ProductShelfTypeEnum.TYPE1);
    }

    @Override
    public Response<Product> getProductByPrincipalMoneyAndPeriod(String productCategoryCode, BigDecimal principalMoney, Integer period) {
        ProductDomain productDomain = productService.getProductDetail(productCategoryCode, principalMoney, period);
        Product product = null;
        if (productDomain != null) {
            product = productDomain.newFacade(false);
        }
        return Response.ok(product);
    }

    @Override
    public Response<Product> getProductByMerchantCodeAndPrincipalMoneyAndPeriod(String merchantCode, BigDecimal principalMoney, Integer period) {
        ProductDomain productDomain = productService.getProductDetailByMerchantCode(merchantCode, principalMoney, period);
        Product product = null;
        if (productDomain != null) {
            product = productDomain.newFacade(false);
        }
        return Response.ok(product);
    }

    @Override
    public Response<List<Product>> getActiveProductList(String productCategoryCode, boolean selectRules) {
        return getProductList(productCategoryCode, selectRules, false, ProductShelfTypeEnum.TYPE1);
    }

    /**
     * 查询结果中只包含active=true的产品
     *
     * @param productCategoryCode
     * @param selectRules
     * @param shelfType
     * @return
     */
    @Override
    public Response<List<Product>> getActiveProductList(String productCategoryCode, boolean selectRules, Integer shelfType) {
        ProductShelfTypeEnum shelfTypeEnum = ProductShelfTypeEnum.getEnum(shelfType);
        if (shelfTypeEnum == null) {
            shelfTypeEnum = ProductShelfTypeEnum.TYPE1;
        }
        return getProductList(productCategoryCode, selectRules, false, shelfTypeEnum);
    }

    private Response<List<Product>> getProductList(String productCategoryCode, boolean selectRules, boolean selectNotSell, ProductShelfTypeEnum shelfTypeEnum) {
        try {
            List<ProductDomain> list = productService.getProductList(productCategoryCode, selectRules, selectNotSell, shelfTypeEnum);
            List<Product> facadeList = new ArrayList<>();
            for (ProductDomain productDomain : list) {
                facadeList.add(productDomain.newFacade(selectRules));
            }
            return Response.ok(facadeList);
        } catch (Exception e) {
            LOGGER.error("查询产品信息失败,productCategoryCode:{},selectRules:{},shelfType:{}", productCategoryCode, selectRules, shelfTypeEnum);
            return Response.error("Product query error! " + e.getMessage());
        }
    }

    @Override
    public Response<Product> getProductDetail(String productCode, boolean selectRules) {
        try {
            boolean selectNotSell = true;
            ProductDomain productDomain = productService.getProductDetail(productCode, selectRules, selectNotSell);
            Product product = null;
            if (productDomain != null) {
                product = productDomain.newFacade(selectRules);
            }
            return Response.ok(product);
        } catch (ProductException e) {
            return Response.error(e.getErrorCode());
        }
    }

    @Override
    public Response<List<Product>> getProductListDetail(List<String> productCodeList, boolean selectRules) {
        if (CollectionUtils.isEmpty(productCodeList)) {
            return Response.ok(null);
        }

        List<Product> productList = new ArrayList<>();
        for (String productCode : productCodeList) {
            Response<Product> productResponse = getProductDetail(productCode, selectRules);
            if (productResponse.isSuccess()) {
                if (productResponse.getData() != null) {
                    productList.add(productResponse.getData());
                }
            }
        }

        return Response.ok(productList);
    }

    @Override
    public Response<List<ProductCategory>> getAllActiveProductCategory() {
        try {
            List<ProductCategory> list = productService.getAllActiveProductCategory();
            return Response.ok(list);
        } catch (ProductException e) {
            return Response.error(e.getErrorCode());
        }
    }

    @Override
    public Response<ProductCategory> getCategoryByCode(String productCategoryCode) {
        try {
            ProductCategory category = productService.getCategoryByCode(productCategoryCode);
            return Response.ok(category);
        } catch (ProductException e) {
            return Response.error(e.getErrorCode());
        }
    }

    @Override
    public Response<List<ConfigResource>> getResource(String typeCode) {
        try {
            List<ConfigResource> configResourceList = productService.getResource(typeCode);
            return Response.ok(configResourceList);
        } catch (ProductException e) {
            return Response.error(e.getErrorCode());
        }
    }

    @Override
    public Response<List<ProductCategory>> getProductCategoriesByMerchantCode(String merchantCode) {
        try {
            List<ProductCategory> productCategoriesByMerchantCode = productService.getProductCategoriesByMerchantCode(merchantCode);
            return Response.ok(productCategoriesByMerchantCode);
        } catch (ProductException e) {
            return Response.error(e.getErrorCode());
        }
    }

    @Override
    public Response<List<ProductCategory>> getAllProductCategory() {
        try {
            List<ProductCategory> productCategories = productService.getAllActiveProductCategory();
            return Response.ok(productCategories);
        } catch (ProductException e) {
            return Response.error(e.getErrorCode());
        }
    }

    @Override
    public Response<List<Product>> getProductByMerchantCode(String merchantCode) {
        try {
            List<Product> products = productService.getProductByMerchantCode(merchantCode);
            return Response.ok(products);
        } catch (ProductException e) {
            return Response.error(e.getErrorCode());
        }
    }


    @Override
    public Response<Product> getProductByArrivalMoneyAndPeriod(String productCategoryCode, BigDecimal arrivalMoney, Integer period) {
        ProductDomain productDomain = productService.getProductDetail(productCategoryCode, arrivalMoney, period);
        Product product = null;
        if (productDomain != null) {
            product = productDomain.newFacade(false);
        }
        return Response.ok(product);
    }

    @Override
    public Response<Product> getProductByArrivalMoneyAndPeriod(String productCategoryCode, BigDecimal arrivalMoney, Integer period, Integer shelfType) {
        if (StringUtils.isEmpty(productCategoryCode) || arrivalMoney == null || period == null || shelfType == null) {
            return Response.error(BasicErrorCodeEnum.PARAM_VALID_ERROR, "param is invalid");
        }
        ProductDomain productDomain = productService.getProductDetailByArrivalMoney(productCategoryCode, arrivalMoney, period, shelfType);
        Product product = null;
        if (productDomain != null) {
            product = productDomain.newFacade(false);
        }
        return Response.ok(product);
    }

    @Override
    public Response updateProductCategoryByCode(ProductCategory productCategory) {
        String code = productCategory.getCode();
        if (StringUtils.isEmpty(code)) {
            return Response.error();
        }

        ProductCategory categoryByCode = productService.getCategoryByCode(code);
        if (categoryByCode == null) {
            return Response.error();
        }

        productService.updateProductCategory(productCategory);

        return Response.ok();
    }

    @Override
    public void addProductCategory(ProductCategory productCategory) {
        productService.addNewProductCategory(productCategory);
    }
}
